#!/usr/bin/python3
# -*- coding: utf-8 -*-

import aiohttp_jinja2, json, logging
from aiohttp import web
from coreweb import setCookie, cookie2user

async def handle_400(request):
    logging.error("400 | Request: %s, %s" % (request.method, request.path))
    return aiohttp_jinja2.render_template('400.html', request, {})

async def handle_404(request):
    logging.error("404 | Request: %s, %s" % (request.method, request.path))
    return aiohttp_jinja2.render_template('404.html', request, {})

async def handle_500(request):
    logging.error("500 | Request: %s, %s" % (request.method, request.path))
    return aiohttp_jinja2.render_template('500.html', request, {})

def create_error_middleware(overrides):

    @web.middleware
    async def error_middleware(request, handler):

        try:
            response = await handler(request)
            if isinstance(response, web.StreamResponse):
                override = overrides.get(response.status)
                if override:
                    return await override(request)
            return response
        except web.HTTPException as ex:
            override = overrides.get(ex.status)
            if override:
                return await override(request)

            raise

    return error_middleware
'''
响应类型处理
'''
def create_resp_middleware():
    @web.middleware
    async def resp_middleware(request, handler):

        try:
            result = await handler(request)
            # StreamResponse
            if isinstance(result, web.StreamResponse):
                return result
            # bytes
            elif isinstance(result, bytes):
                resp = web.Response(body=result)
                resp.content_type = 'application/octet-stream'
            elif isinstance(result, str):
                if result.startswith('redirect:'):
                    resp = web.HTTPFound(result[9:])
                else:
                    resp = web.Response(body=result.encode('utf-8'))
                    resp.content_type = 'text/html;charset=utf-8'
            elif isinstance(result, dict):
                if hasattr(request, '__template__'):
                    if hasattr(request, '__user__') and request.__user__:
                        result['__user__'] = request.__user__
                    resp = web.Response(body=request.app['__templating__'].get_template(request.__template__).render(**result).encode('utf-8'))
                    resp.content_type = 'text/html;charset=utf-8'
                else:
                    resp = web.Response(body=json.dumps(result, default=lambda obj: obj.__dict__).encode('utf-8'))
                    resp.content_type = 'application/json;charset=utf-8'
            elif isinstance(result, int) and result >= 100 and result < 600:
                resp = web.Response(status=result)
            elif isinstance(result, tuple) and len(result) == 2:
                t, m = result
                if isinstance(t, int) and t >= 100 and t < 600:
                    resp = web.Response(status=t, body=str(m))
            else:
                resp = web.Response(body=str(result).encode('utf-8'))
                resp.content_type = 'text/plain;charset=utf-8'
            user = request.__user__
            setCookie(user, resp)
            return resp
        except web.HTTPException as ex:
            logging.error(ex)

    return resp_middleware
'''
处理函数日志记录
'''
def create_logs_middleware():
    @web.middleware
    async def logs_middleware(request, handler):
        # 记录日志:
        logging.warn('Request: %s %s' % (request.method, request.path))
        # 继续处理请求:
        return (await handler(request))
    return logs_middleware

'''
用户cookie验证
'''
def create_auth_middleware():
    @web.middleware
    async def auth_middleware(request, handler):
        logging.info('check user: %s %s' % (request.method, request.path))
        request.__user__ = None
        user = await cookie2user(request)
        if user:
            logging.info('set current user: %s' % user.email)
            request.__user__ = user
        if 'user/edit' in request.path and (request.__user__ is None or not request.__user__.admin):
            return web.HTTPFound('/login')
        return (await handler(request))
    return auth_middleware

def setup_middlewares(app):
    error_middleware = create_error_middleware({
        400: handle_400,
        404: handle_404,
        500: handle_500
    })
    # 拦截器先注册后执行
    app.middlewares.append(create_logs_middleware())
    app.middlewares.append(create_auth_middleware())
    app.middlewares.append(create_resp_middleware())
    app.middlewares.append(error_middleware)